/**
 * 
 */
package fb.chatter.utils;

import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;

import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.apache.xerces.parsers.DOMParser;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
 * @author hoannguyen
 * 
 */
public final class XMLUtils {

	/**
	 * To build the XML Document with the given XML string
	 * 
	 * @param xml
	 * @return
	 */
	public static Document buildXMLDocument(String xml) {

		try {
			DOMParser parser = new DOMParser();
			parser.setFeature("http://xml.org/sax/features/namespaces", false);
			StringReader xmlReader = new StringReader(xml);
			InputSource is = new InputSource(xmlReader);
			parser.parse(is);
			return parser.getDocument();
		} catch (SAXException e) {
			ExceptionUtils.log(e);
		} catch (IOException e) {
			ExceptionUtils.log(e);
		}

		return null;
	}
	
	/**
	 * To convert a NodeList object to a List<Node>
	 * 
	 * @param nodeList
	 * @return List<Node> that contains at least 0 element, never null.
	 */
	public static List<Node> convert(NodeList nodeList) {

		List<Node> list = new ArrayList<Node>();

		if (nodeList == null) {
			return list;
		}
		for (int i = 0; i < nodeList.getLength(); i++) {
			Node node = nodeList.item(i);
			list.add(node);
		}
		return list;
	}

	/**
	 * To get element in the given XML document with the given xpathExpression
	 * 
	 * @param doc
	 * @param xpathExpression
	 * @return
	 */
	public static Element getElement(Document doc, String xpathExpression) {

		if (doc == null) {
			return null;
		}

		try {
			XPath xpath = XPathFactory.newInstance().newXPath();
			XPathExpression xExp = xpath.compile(xpathExpression);
			NodeList domNodeList = (NodeList) xExp.evaluate(doc, XPathConstants.NODESET);
			List<Node> nodeList = XMLUtils.convert(domNodeList);
			if(nodeList.size() > 0){
				return (Element) nodeList.get(0);
			}
			
		} catch (XPathExpressionException e) {
			ExceptionUtils.log(e);
		}

		return null;
	}
}
